/*! * \brief pixExpandBinaryReplicate() * * \param[in] pixs 1 bpp * \param[in] xfact integer scale factor for horiz. replicative expansion * \param[in] yfact integer scale factor for vertical replicative expansion * \return pixd scaled up, or NULL on error */ PIX * pixExpandBinaryReplicate(PIX *pixs, l_int32 xfact, l_int32 yfact) { l_int32 w, h, d, wd, hd, wpls, wpld, i, j, k, start; l_uint32 *datas, *datad, *lines, *lined; PIX *pixd; PROCNAME("pixExpandBinaryReplicate"); if (!pixs) return (PIX *)ERROR_PTR("pixs not defined", procName, NULL); pixGetDimensions(pixs, &w, &h, &d); if (d != 1) return (PIX *)ERROR_PTR("pixs not binary", procName, NULL); if (xfact <= 0 || yfact <= 0) return (PIX *)ERROR_PTR("invalid scale factor: <= 0", procName, NULL); if (xfact == yfact) { if (xfact == 1) return pixCopy(NULL, pixs); if (xfact == 2 || xfact == 4 || xfact == 8 || xfact == 16) return pixExpandBinaryPower2(pixs, xfact); } wpls = pixGetWpl(pixs); datas = pixGetData(pixs); wd = xfact * w; hd = yfact * h; if ((pixd = pixCreate(wd, hd, 1)) == NULL) return (PIX *)ERROR_PTR("pixd not made", procName, NULL); pixCopyResolution(pixd, pixs); pixScaleResolution(pixd, (l_float32)xfact, (l_float32)yfact); wpld = pixGetWpl(pixd); datad = pixGetData(pixd); for (i = 0; i < h; i++) { lines = datas + i * wpls; lined = datad + yfact * i * wpld; for (j = 0; j < w; j++) { /* replicate pixels on a single line */ if (GET_DATA_BIT(lines, j)) { start = xfact * j; for (k = 0; k < xfact; k++) SET_DATA_BIT(lined, start + k); } } for (k = 1; k < yfact; k++) /* replicate the line */ memcpy(lined + k * wpld, lined, 4 * wpld); } return pixd; }
/*! * pixExpandBinaryReplicate() * * Input: pixs (1 bpp) * factor (integer scale factor for replicative expansion) * Return: pixd (scaled up), or null on error */ PIX * pixExpandBinaryReplicate(PIX *pixs, l_int32 factor) { l_int32 w, h, d, wd, hd, wpls, wpld, i, j, k, start; l_uint32 *datas, *datad, *lines, *lined; PIX *pixd; PROCNAME("pixExpandBinaryReplicate"); if (!pixs) return (PIX *)ERROR_PTR("pixs not defined", procName, NULL); pixGetDimensions(pixs, &w, &h, &d); if (d != 1) return (PIX *)ERROR_PTR("pixs not binary", procName, NULL); if (factor <= 0) return (PIX *)ERROR_PTR("factor <= 0; invalid", procName, NULL); if (factor == 1) return pixCopy(NULL, pixs); if (factor == 2 || factor == 4 || factor == 8 || factor == 16) return pixExpandBinaryPower2(pixs, factor); wpls = pixGetWpl(pixs); datas = pixGetData(pixs); wd = factor * w; hd = factor * h; if ((pixd = pixCreate(wd, hd, 1)) == NULL) return (PIX *)ERROR_PTR("pixd not made", procName, NULL); pixCopyResolution(pixd, pixs); pixScaleResolution(pixd, (l_float32)factor, (l_float32)factor); wpld = pixGetWpl(pixd); datad = pixGetData(pixd); for (i = 0; i < h; i++) { lines = datas + i * wpls; lined = datad + factor * i * wpld; for (j = 0; j < w; j++) { if (GET_DATA_BIT(lines, j)) { start = factor * j; for (k = 0; k < factor; k++) SET_DATA_BIT(lined, start + k); } } for (k = 1; k < factor; k++) memcpy(lined + k * wpld, lined, 4 * wpld); } return pixd; }
l_int32 DoPageSegmentation(PIX *pixs, /* should be at least 300 ppi */ l_int32 which) /* 1, 2, 3, 4 */ { char buf[256]; l_int32 zero; BOXA *boxatm, *boxahm; PIX *pixr; /* image reduced to 150 ppi */ PIX *pixhs; /* image of halftone seed, 150 ppi */ PIX *pixm; /* image of mask of components, 150 ppi */ PIX *pixhm1; /* image of halftone mask, 150 ppi */ PIX *pixhm2; /* image of halftone mask, 300 ppi */ PIX *pixht; /* image of halftone components, 150 ppi */ PIX *pixnht; /* image without halftone components, 150 ppi */ PIX *pixi; /* inverted image, 150 ppi */ PIX *pixvws; /* image of vertical whitespace, 150 ppi */ PIX *pixm1; /* image of closed textlines, 150 ppi */ PIX *pixm2; /* image of refined text line mask, 150 ppi */ PIX *pixm3; /* image of refined text line mask, 300 ppi */ PIX *pixb1; /* image of text block mask, 150 ppi */ PIX *pixb2; /* image of text block mask, 300 ppi */ PIX *pixnon; /* image of non-text or halftone, 150 ppi */ PIX *pix1, *pix2, *pix3, *pix4; PIXA *pixa; PIXCMAP *cmap; PTAA *ptaa; l_int32 ht_flag = 0; l_int32 ws_flag = 0; l_int32 text_flag = 0; l_int32 block_flag = 0; PROCNAME("DoPageSegmentation"); if (which == 1) ht_flag = 1; else if (which == 2) ws_flag = 1; else if (which == 3) text_flag = 1; else if (which == 4) block_flag = 1; else return ERROR_INT("invalid parameter: not in [1...4]", procName, 1); pixa = pixaCreate(0); lept_mkdir("lept/livre"); /* Reduce to 150 ppi */ pix1 = pixScaleToGray2(pixs); if (ws_flag || ht_flag || block_flag) pixaAddPix(pixa, pix1, L_COPY); if (which == 1) pixWrite("/tmp/lept/livre/orig.gray.150.png", pix1, IFF_PNG); pixDestroy(&pix1); pixr = pixReduceRankBinaryCascade(pixs, 1, 0, 0, 0); /* Get seed for halftone parts */ pix1 = pixReduceRankBinaryCascade(pixr, 4, 4, 3, 0); pix2 = pixOpenBrick(NULL, pix1, 5, 5); pixhs = pixExpandBinaryPower2(pix2, 8); if (ht_flag) pixaAddPix(pixa, pixhs, L_COPY); if (which == 1) pixWrite("/tmp/lept/livre/htseed.150.png", pixhs, IFF_PNG); pixDestroy(&pix1); pixDestroy(&pix2); /* Get mask for connected regions */ pixm = pixCloseSafeBrick(NULL, pixr, 4, 4); if (ht_flag) pixaAddPix(pixa, pixm, L_COPY); if (which == 1) pixWrite("/tmp/lept/livre/ccmask.150.png", pixm, IFF_PNG); /* Fill seed into mask to get halftone mask */ pixhm1 = pixSeedfillBinary(NULL, pixhs, pixm, 4); if (ht_flag) pixaAddPix(pixa, pixhm1, L_COPY); if (which == 1) pixWrite("/tmp/lept/livre/htmask.150.png", pixhm1, IFF_PNG); pixhm2 = pixExpandBinaryPower2(pixhm1, 2); /* Extract halftone stuff */ pixht = pixAnd(NULL, pixhm1, pixr); if (which == 1) pixWrite("/tmp/lept/livre/ht.150.png", pixht, IFF_PNG); /* Extract non-halftone stuff */ pixnht = pixXor(NULL, pixht, pixr); if (text_flag) pixaAddPix(pixa, pixnht, L_COPY); if (which == 1) pixWrite("/tmp/lept/livre/text.150.png", pixnht, IFF_PNG); pixZero(pixht, &zero); if (zero) fprintf(stderr, "No halftone parts found\n"); else fprintf(stderr, "Halftone parts found\n"); /* Get bit-inverted image */ pixi = pixInvert(NULL, pixnht); if (ws_flag) pixaAddPix(pixa, pixi, L_COPY); if (which == 1) pixWrite("/tmp/lept/livre/invert.150.png", pixi, IFF_PNG); /* The whitespace mask will break textlines where there * is a large amount of white space below or above. * We can prevent this by identifying regions of the * inverted image that have large horizontal (bigger than * the separation between columns) and significant * vertical extent (bigger than the separation between * textlines), and subtracting this from the whitespace mask. */ pix1 = pixMorphCompSequence(pixi, "o80.60", 0); pix2 = pixSubtract(NULL, pixi, pix1); if (ws_flag) pixaAddPix(pixa, pix2, L_COPY); pixDestroy(&pix1); /* Identify vertical whitespace by opening inverted image */ pix3 = pixOpenBrick(NULL, pix2, 5, 1); /* removes thin vertical lines */ pixvws = pixOpenBrick(NULL, pix3, 1, 200); /* gets long vertical lines */ if (text_flag || ws_flag) pixaAddPix(pixa, pixvws, L_COPY); if (which == 1) pixWrite("/tmp/lept/livre/vertws.150.png", pixvws, IFF_PNG); pixDestroy(&pix2); pixDestroy(&pix3); /* Get proto (early processed) text line mask. */ /* First close the characters and words in the textlines */ pixm1 = pixCloseSafeBrick(NULL, pixnht, 30, 1); if (text_flag) pixaAddPix(pixa, pixm1, L_COPY); if (which == 1) pixWrite("/tmp/lept/livre/textmask1.150.png", pixm1, IFF_PNG); /* Next open back up the vertical whitespace corridors */ pixm2 = pixSubtract(NULL, pixm1, pixvws); if (which == 1) pixWrite("/tmp/lept/livre/textmask2.150.png", pixm2, IFF_PNG); /* Do a small opening to remove noise */ pixOpenBrick(pixm2, pixm2, 3, 3); if (text_flag) pixaAddPix(pixa, pixm2, L_COPY); if (which == 1) pixWrite("/tmp/lept/livre/textmask3.150.png", pixm2, IFF_PNG); pixm3 = pixExpandBinaryPower2(pixm2, 2); /* Join pixels vertically to make text block mask */ pixb1 = pixMorphSequence(pixm2, "c1.10 + o4.1", 0); if (block_flag) pixaAddPix(pixa, pixb1, L_COPY); if (which == 1) pixWrite("/tmp/lept/livre/textblock1.150.png", pixb1, IFF_PNG); /* Solidify the textblock mask and remove noise: * (1) For each c.c., close the blocks and dilate slightly * to form a solid mask. * (2) Small horizontal closing between components * (3) Open the white space between columns, again * (4) Remove small components */ pix1 = pixMorphSequenceByComponent(pixb1, "c30.30 + d3.3", 8, 0, 0, NULL); pixCloseSafeBrick(pix1, pix1, 10, 1); if (block_flag) pixaAddPix(pixa, pix1, L_COPY); pix2 = pixSubtract(NULL, pix1, pixvws); pix3 = pixSelectBySize(pix2, 25, 5, 8, L_SELECT_IF_BOTH, L_SELECT_IF_GTE, NULL); if (block_flag) pixaAddPix(pixa, pix3, L_COPY); if (which == 1) pixWrite("/tmp/lept/livre/textblock2.150.png", pix3, IFF_PNG); pixb2 = pixExpandBinaryPower2(pix3, 2); pixDestroy(&pix1); pixDestroy(&pix2); pixDestroy(&pix3); /* Identify the outlines of each textblock */ ptaa = pixGetOuterBordersPtaa(pixb2); pix1 = pixRenderRandomCmapPtaa(pixb2, ptaa, 1, 8, 1); cmap = pixGetColormap(pix1); pixcmapResetColor(cmap, 0, 130, 130, 130); /* set interior to gray */ if (which == 1) pixWrite("/tmp/lept/livre/textblock3.300.png", pix1, IFF_PNG); pixDisplayWithTitle(pix1, 480, 360, "textblock mask with outlines", DFLAG); ptaaDestroy(&ptaa); pixDestroy(&pix1); /* Fill line mask (as seed) into the original */ pix1 = pixSeedfillBinary(NULL, pixm3, pixs, 8); pixOr(pixm3, pixm3, pix1); pixDestroy(&pix1); if (which == 1) pixWrite("/tmp/lept/livre/textmask.300.png", pixm3, IFF_PNG); pixDisplayWithTitle(pixm3, 480, 360, "textline mask 4", DFLAG); /* Fill halftone mask (as seed) into the original */ pix1 = pixSeedfillBinary(NULL, pixhm2, pixs, 8); pixOr(pixhm2, pixhm2, pix1); pixDestroy(&pix1); if (which == 1) pixWrite("/tmp/lept/livre/htmask.300.png", pixhm2, IFF_PNG); pixDisplayWithTitle(pixhm2, 520, 390, "halftonemask 2", DFLAG); /* Find objects that are neither text nor halftones */ pix1 = pixSubtract(NULL, pixs, pixm3); /* remove text pixels */ pixnon = pixSubtract(NULL, pix1, pixhm2); /* remove halftone pixels */ pixDestroy(&pix1); if (which == 1) pixWrite("/tmp/lept/livre/other.300.png", pixnon, IFF_PNG); pixDisplayWithTitle(pixnon, 540, 420, "other stuff", DFLAG); /* Write out b.b. for text line mask and halftone mask components */ boxatm = pixConnComp(pixm3, NULL, 4); boxahm = pixConnComp(pixhm2, NULL, 8); if (which == 1) { boxaWrite("/tmp/lept/livre/textmask.boxa", boxatm); boxaWrite("/tmp/lept/livre/htmask.boxa", boxahm); } pix1 = pixaDisplayTiledAndScaled(pixa, 8, 250, 4, 0, 25, 2); pixDisplay(pix1, 0, 375 * (which - 1)); snprintf(buf, sizeof(buf), "/tmp/lept/livre/segout.%d.png", which); pixWrite(buf, pix1, IFF_PNG); pixDestroy(&pix1); pixaDestroy(&pixa); /* clean up to test with valgrind */ pixDestroy(&pixr); pixDestroy(&pixhs); pixDestroy(&pixm); pixDestroy(&pixhm1); pixDestroy(&pixhm2); pixDestroy(&pixht); pixDestroy(&pixi); pixDestroy(&pixnht); pixDestroy(&pixvws); pixDestroy(&pixm1); pixDestroy(&pixm2); pixDestroy(&pixm3); pixDestroy(&pixb1); pixDestroy(&pixb2); pixDestroy(&pixnon); boxaDestroy(&boxatm); boxaDestroy(&boxahm); return 0; }
main(int argc, char **argv) { l_int32 i, w, h, same; char filename[][64] = {BINARY_IMAGE, TWO_BPP_IMAGE_NO_CMAP, TWO_BPP_IMAGE_CMAP, FOUR_BPP_IMAGE_NO_CMAP, FOUR_BPP_IMAGE_CMAP, EIGHT_BPP_IMAGE_NO_CMAP, EIGHT_BPP_IMAGE_CMAP, RGB_IMAGE}; BOX *box; PIX *pix, *pixs, *pixt, *pixt1, *pixt2, *pixt3, *pixt4, *pixt5, *pixd; static char mainName[] = "expand_reg"; if (argc != 1) exit(ERROR_INT(" Syntax: expand_reg", mainName, 1)); pixDisplayWrite(NULL, -1); for (i = 0; i < 8; i++) { pixs = pixRead(filename[i]); pixt = pixExpandReplicate(pixs, 2); pixDisplayWrite(pixt, 1); pixDestroy(&pixt); pixt = pixExpandReplicate(pixs, 3); pixDisplayWrite(pixt, 1); pixDestroy(&pixt); if (i == 4) { pixt = pixScale(pixs, 3.0, 3.0); pixWrite("/tmp/junkpixt.png", pixt, IFF_PNG); pixDestroy(&pixt); } pixDestroy(&pixs); } pix = pixRead("test1.png"); pixGetDimensions(pix, &w, &h, NULL); for (i = 1; i <= 15; i++) { box = boxCreate(13 * i, 13 * i, w - 13 * i, h - 13 * i); pixs = pixClipRectangle(pix, box, NULL); pixt = pixExpandReplicate(pixs, 3); pixDisplayWrite(pixt, 1); boxDestroy(&box); pixDestroy(&pixt); pixDestroy(&pixs); } pixDestroy(&pix); pixs = pixRead("speckle.png"); /* Test 2x expansion of 1 bpp */ pixt = pixExpandBinaryPower2(pixs, 2); pixDisplayWrite(pixt, 1); pixd = pixReduceRankBinary2(pixt, 4, NULL); pixEqual(pixs, pixd, &same); if (!same) fprintf(stderr, "Error in 2x 1bpp expansion\n"); pixDestroy(&pixt); pixDestroy(&pixd); /* Test 2x expansion of 2 bpp */ pixt1 = pixConvert1To2(NULL, pixs, 3, 0); pixt2 = pixExpandReplicate(pixt1, 2); pixDisplayWrite(pixt2, 1); pixt3 = pixConvertTo8(pixt2, FALSE); pixt4 = pixThresholdToBinary(pixt3, 250); pixd = pixReduceRankBinary2(pixt4, 4, NULL); pixEqual(pixs, pixd, &same); if (!same) fprintf(stderr, "Error in 2x 2bpp expansion\n"); pixt5 = pixExpandBinaryPower2(pixd, 2); pixDisplayWrite(pixt5, 1); pixDestroy(&pixt1); pixDestroy(&pixt2); pixDestroy(&pixt3); pixDestroy(&pixt4); pixDestroy(&pixt5); pixDestroy(&pixd); /* Test 4x expansion of 4 bpp */ pixt1 = pixConvert1To4(NULL, pixs, 15, 0); pixt2 = pixExpandReplicate(pixt1, 4); pixDisplayWrite(pixt2, 2); pixt3 = pixConvertTo8(pixt2, FALSE); pixt4 = pixThresholdToBinary(pixt3, 250); pixDisplayWrite(pixt4, 2); pixd = pixReduceRankBinaryCascade(pixt4, 4, 4, 0, 0); pixEqual(pixs, pixd, &same); if (!same) fprintf(stderr, "Error in 4x 4bpp expansion\n"); pixDestroy(&pixt1); pixDestroy(&pixt2); pixDestroy(&pixt3); pixDestroy(&pixt4); pixDestroy(&pixd); /* Test 8x expansion of 8 bpp */ pixt1 = pixConvertTo8(pixs, FALSE); pixt2 = pixExpandReplicate(pixt1, 8); pixDisplayWrite(pixt2, 4); pixt3 = pixThresholdToBinary(pixt2, 250); pixDisplayWrite(pixt3, 4); pixd = pixReduceRankBinaryCascade(pixt3, 4, 4, 4, 0); pixEqual(pixs, pixd, &same); if (!same) fprintf(stderr, "Error in 4x 4bpp expansion\n"); pixDestroy(&pixt1); pixDestroy(&pixt2); pixDestroy(&pixt3); pixDestroy(&pixd); pixDestroy(&pixs); pixDisplayMultiple("/tmp/junk_write_display*"); return 0; }
main(int argc, char **argv) { l_int32 h; l_float32 scalefactor; BOX *box; BOXA *boxa1, *boxa2; BOXAA *baa; PIX *pix1, *pix2, *pix3, *pix4, *pix5, *pix6, *pix7, *pix8, *pix9; L_REGPARAMS *rp; if (regTestSetup(argc, argv, &rp)) return 1; lept_rmdir("segtest"); lept_mkdir("segtest"); baa = boxaaCreate(5); /* Image region input. */ pix1 = pixRead("wet-day.jpg"); pix2 = pixScaleToSize(pix1, WIDTH, 0); pixWrite("/tmp/segtest/0.jpg", pix2, IFF_JFIF_JPEG); regTestCheckFile(rp, "/tmp/segtest/0.jpg"); /* 0 */ box = boxCreate(105, 161, 620, 872); /* image region */ boxa1 = boxaCreate(1); boxaAddBox(boxa1, box, L_INSERT); boxaaAddBoxa(baa, boxa1, L_INSERT); pixDestroy(&pix1); pixDestroy(&pix2); /* Compute image region at w = 2 * WIDTH */ pix1 = pixRead("candelabrum-11.jpg"); pix2 = pixScaleToSize(pix1, WIDTH, 0); pix3 = pixConvertTo1(pix2, 100); pix4 = pixExpandBinaryPower2(pix3, 2); /* w = 2 * WIDTH */ pix5 = pixGenHalftoneMask(pix4, NULL, NULL, 1); pix6 = pixMorphSequence(pix5, "c20.1 + c1.20", 0); pix7 = pixMaskConnComp(pix6, 8, &boxa1); pix8 = pixReduceBinary2(pix7, NULL); /* back to w = WIDTH */ pix9 = pixBackgroundNormSimple(pix2, pix8, NULL); pixWrite("/tmp/segtest/1.jpg", pix9, IFF_JFIF_JPEG); regTestCheckFile(rp, "/tmp/segtest/1.jpg"); /* 1 */ boxa2 = boxaTransform(boxa1, 0, 0, 0.5, 0.5); /* back to w = WIDTH */ boxaaAddBoxa(baa, boxa2, L_INSERT); pixDestroy(&pix1); pixDestroy(&pix2); pixDestroy(&pix3); pixDestroy(&pix4); pixDestroy(&pix5); pixDestroy(&pix6); pixDestroy(&pix7); pixDestroy(&pix8); pixDestroy(&pix9); boxaDestroy(&boxa1); /* Use mask to find image region */ pix1 = pixRead("lion-page.00016.jpg"); pix2 = pixScaleToSize(pix1, WIDTH, 0); pixWrite("/tmp/segtest/2.jpg", pix2, IFF_JFIF_JPEG); regTestCheckFile(rp, "/tmp/segtest/2.jpg"); /* 2 */ pix3 = pixRead("lion-mask.00016.tif"); pix4 = pixScaleToSize(pix3, WIDTH, 0); boxa1 = pixConnComp(pix4, NULL, 8); boxaaAddBoxa(baa, boxa1, L_INSERT); pixDestroy(&pix1); pixDestroy(&pix2); pixDestroy(&pix3); pixDestroy(&pix4); /* Compute image region at full res */ pix1 = pixRead("rabi.png"); scalefactor = (l_float32)WIDTH / (l_float32)pixGetWidth(pix1); pix2 = pixScaleToGray(pix1, scalefactor); pixWrite("/tmp/segtest/3.jpg", pix2, IFF_JFIF_JPEG); regTestCheckFile(rp, "/tmp/segtest/3.jpg"); /* 3 */ pix3 = pixGenHalftoneMask(pix1, NULL, NULL, 0); pix4 = pixMorphSequence(pix3, "c20.1 + c1.20", 0); boxa1 = pixConnComp(pix4, NULL, 8); boxa2 = boxaTransform(boxa1, 0, 0, scalefactor, scalefactor); boxaaAddBoxa(baa, boxa2, L_INSERT); pixDestroy(&pix1); pixDestroy(&pix2); pixDestroy(&pix3); pixDestroy(&pix4); boxaDestroy(&boxa1); /* Page with no image regions */ pix1 = pixRead("lucasta-47.jpg"); pix2 = pixScaleToSize(pix1, WIDTH, 0); boxa1 = boxaCreate(1); pixWrite("/tmp/segtest/4.jpg", pix2, IFF_JFIF_JPEG); regTestCheckFile(rp, "/tmp/segtest/4.jpg"); /* 4 */ boxaaAddBoxa(baa, boxa1, L_INSERT); pixDestroy(&pix1); pixDestroy(&pix2); /* Page that is all image */ pix1 = pixRead("map1.jpg"); pix2 = pixScaleToSize(pix1, WIDTH, 0); pixWrite("/tmp/segtest/5.jpg", pix2, IFF_JFIF_JPEG); regTestCheckFile(rp, "/tmp/segtest/5.jpg"); /* 5 */ h = pixGetHeight(pix2); box = boxCreate(0, 0, WIDTH, h); boxa1 = boxaCreate(1); boxaAddBox(boxa1, box, L_INSERT); boxaaAddBoxa(baa, boxa1, L_INSERT); pixDestroy(&pix1); pixDestroy(&pix2); /* Save the boxaa file */ boxaaWrite("/tmp/segtest/seg.baa", baa); regTestCheckFile(rp, "/tmp/segtest/seg.baa"); /* 6 */ /* Do the conversion */ l_pdfSetDateAndVersion(FALSE); convertSegmentedFilesToPdf("/tmp/segtest", ".jpg", 100, L_G4_ENCODE, 140, baa, 75, 0.6, "Segmentation Test", "/tmp/pdfseg.7.pdf"); regTestCheckFile(rp, "/tmp/pdfseg.7.pdf"); /* 7 */ boxaaDestroy(&baa); return regTestCleanup(rp); }
main(int argc, char **argv) { char *filein, *fileout; l_int32 thresh; PIX *pixs, *pixg, *pixb; PIX *pixmask4, *pixseed4, *pixsf4, *pixd4, *pixd; static char mainName[] = "pagesegtest2"; if (argc != 4) exit(ERROR_INT(" Syntax: pagesegtest2 filein thresh fileout", mainName, 1)); filein = argv[1]; thresh = atoi(argv[2]); fileout = argv[3]; /* Get a 1 bpp version of the page */ if ((pixs = pixRead(filein)) == NULL) exit(ERROR_INT("pixs not made", mainName, 1)); if (pixGetDepth(pixs) == 32) pixg = pixConvertRGBToGrayFast(pixs); else pixg = pixClone(pixs); if (pixGetDepth(pixg) == 8) pixb = pixThresholdToBinary(pixg, thresh); else pixb = pixClone(pixg); /* Make seed and mask, and fill seed into mask */ pixseed4 = pixMorphSequence(pixb, seed_sequence, 0); pixmask4 = pixMorphSequence(pixb, mask_sequence, 0); pixsf4 = pixSeedfillBinary(NULL, pixseed4, pixmask4, 8); pixd4 = pixMorphSequence(pixsf4, dilation_sequence, 0); /* Mask at full resolution */ pixd = pixExpandBinaryPower2(pixd4, 4); pixWrite(fileout, pixd, IFF_TIFF_G4); /* Extract non-image parts (e.g., text) at full resolution */ pixSubtract(pixb, pixb, pixd); pixDisplayWithTitle(pixseed4, 400, 100, "halftone seed", DFLAG); pixDisplayWithTitle(pixmask4, 100, 100, "halftone seed mask", DFLAG); pixDisplayWithTitle(pixd4, 700, 100, "halftone mask", DFLAG); pixDisplayWithTitle(pixb, 1000, 100, "non-halftone", DFLAG); #if 1 pixWrite("junkseed", pixseed4, IFF_TIFF_G4); pixWrite("junkmask", pixmask4, IFF_TIFF_G4); pixWrite("junkfill", pixd4, IFF_TIFF_G4); pixWrite("junktext", pixb, IFF_TIFF_G4); #endif pixDestroy(&pixs); pixDestroy(&pixg); pixDestroy(&pixb); pixDestroy(&pixseed4); pixDestroy(&pixmask4); pixDestroy(&pixsf4); pixDestroy(&pixd4); pixDestroy(&pixd); exit(0); }