/*! * pixcmapShiftIntensity() * * Input: colormap * fraction (between -1.0 and +1.0) * Return: 0 if OK; 1 on error * * Notes: * - in-place transform * - This does a proportional shift of the intensity for each color. * - If fraction < 0.0, it moves all colors towards (0,0,0). * This darkens the image. * - If fraction > 0.0, it moves all colors towards (255,255,255) * This fades the image. * - The equivalent transform can be accomplished with pixcmapGammaTRC(), * but it is considerably more difficult (see numaGammaTRC()). */ l_int32 pixcmapShiftIntensity(PIXCMAP *cmap, l_float32 fraction) { l_int32 i, ncolors, rval, gval, bval; PROCNAME("pixcmapShiftIntensity"); if (!cmap) return ERROR_INT("cmap not defined", procName, 1); if (fraction < -1.0 || fraction > 1.0) return ERROR_INT("fraction not in [-1.0, 1.0]", procName, 1); ncolors = pixcmapGetCount(cmap); for (i = 0; i < ncolors; i++) { pixcmapGetColor(cmap, i, &rval, &gval, &bval); if (fraction < 0.0) pixcmapResetColor(cmap, i, (l_int32)((1.0 + fraction) * rval), (l_int32)((1.0 + fraction) * gval), (l_int32)((1.0 + fraction) * bval)); else pixcmapResetColor(cmap, i, rval + (l_int32)(fraction * (255 - rval)), gval + (l_int32)(fraction * (255 - gval)), bval + (l_int32)(fraction * (255 - bval))); } return 0; }
/*! * pixcmapContrastTRC() * * Input: colormap * factor (generally between 0.0 (no enhancement) * and 1.0, but can be larger than 1.0) * Return: 0 if OK; 1 on error * * Notes: * - in-place transform * - see pixContrastTRC() and numaContrastTRC() in enhance.c for * description and use of transform */ l_int32 pixcmapContrastTRC(PIXCMAP *cmap, l_float32 factor) { l_int32 i, ncolors, rval, gval, bval, trval, tgval, tbval; NUMA *nac; PROCNAME("pixcmapContrastTRC"); if (!cmap) return ERROR_INT("cmap not defined", procName, 1); if (factor < 0.0) { L_WARNING("factor must be >= 0.0; setting to 0.0", procName); factor = 0.0; } if ((nac = numaContrastTRC(factor)) == NULL) return ERROR_INT("nac not made", procName, 1); ncolors = pixcmapGetCount(cmap); for (i = 0; i < ncolors; i++) { pixcmapGetColor(cmap, i, &rval, &gval, &bval); numaGetIValue(nac, rval, &trval); numaGetIValue(nac, gval, &tgval); numaGetIValue(nac, bval, &tbval); pixcmapResetColor(cmap, i, trval, tgval, tbval); } numaDestroy(&nac); return 0; }
/*! * pixcmapSetBlackAndWhite() * * Input: cmap * setblack (0 for no operation; 1 to set darkest color to black) * setwhite (0 for no operation; 1 to set lightest color to white) * Return: 0 if OK, 1 on error */ l_int32 pixcmapSetBlackAndWhite(PIXCMAP *cmap, l_int32 setblack, l_int32 setwhite) { l_int32 index; PROCNAME("pixcmapSetBlackAndWhite"); if (!cmap) return ERROR_INT("cmap not defined", procName, 1); if (setblack) { pixcmapGetRankIntensity(cmap, 0.0, &index); pixcmapResetColor(cmap, index, 0, 0, 0); } if (setwhite) { pixcmapGetRankIntensity(cmap, 1.0, &index); pixcmapResetColor(cmap, index, 255, 255, 255); } return 0; }
/*! * pixcmapConvertHSVToRGB() * * Input: colormap * Return: 0 if OK; 1 on error * * Notes: * - in-place transform * - See convertRGBToHSV() for def'n of HSV space. * - replaces: h --> r, s --> g, v --> b */ l_int32 pixcmapConvertHSVToRGB(PIXCMAP *cmap) { l_int32 i, ncolors, rval, gval, bval, hval, sval, vval; PROCNAME("pixcmapConvertHSVToRGB"); if (!cmap) return ERROR_INT("cmap not defined", procName, 1); ncolors = pixcmapGetCount(cmap); for (i = 0; i < ncolors; i++) { pixcmapGetColor(cmap, i, &hval, &sval, &vval); convertHSVToRGB(hval, sval, vval, &rval, &gval, &bval); pixcmapResetColor(cmap, i, rval, gval, bval); } return 0; }
/*! * pixcmapColorToGray() * * Input: cmap * rwt, gwt, bwt (non-negative; these should add to 1.0) * Return: cmap (gray), or null on error * * Notes: * (1) This creates a gray colormap from an arbitrary colormap. * (2) In use, attach the output gray colormap to the pix * (or a copy of it) that provided the input colormap. */ PIXCMAP * pixcmapColorToGray(PIXCMAP *cmaps, l_float32 rwt, l_float32 gwt, l_float32 bwt) { l_int32 i, n, rval, gval, bval, val; l_float32 sum; PIXCMAP *cmapd; PROCNAME("pixcmapColorToGray"); if (!cmaps) return (PIXCMAP *)ERROR_PTR("cmaps not defined", procName, NULL); if (rwt < 0.0 || gwt < 0.0 || bwt < 0.0) return (PIXCMAP *)ERROR_PTR("weights not all >= 0.0", procName, NULL); /* Make sure the sum of weights is 1.0; otherwise, you can get * overflow in the gray value. */ sum = rwt + gwt + bwt; if (sum == 0.0) { L_WARNING("all weights zero; setting equal to 1/3", procName); rwt = gwt = bwt = 0.33333; sum = 1.0; } if (L_ABS(sum - 1.0) > 0.0001) { /* maintain ratios with sum == 1.0 */ L_WARNING("weights don't sum to 1; maintaining ratios", procName); rwt = rwt / sum; gwt = gwt / sum; bwt = bwt / sum; } cmapd = pixcmapCopy(cmaps); n = pixcmapGetCount(cmapd); for (i = 0; i < n; i++) { pixcmapGetColor(cmapd, i, &rval, &gval, &bval); val = (l_int32)(rwt * rval + gwt * gval + bwt * bval + 0.5); pixcmapResetColor(cmapd, i, val, val, val); } return cmapd; }
/*! * pixcmapGammaTRC() * * Input: colormap * gamma (gamma correction; must be > 0.0) * minval (input value that gives 0 for output; can be < 0) * maxval (input value that gives 255 for output; can be > 255) * Return: 0 if OK; 1 on error * * Notes: * - in-place transform * - see pixGammaTRC() and numaGammaTRC() in enhance.c for * description and use of transform */ l_int32 pixcmapGammaTRC(PIXCMAP *cmap, l_float32 gamma, l_int32 minval, l_int32 maxval) { l_int32 rval, gval, bval, trval, tgval, tbval, i, ncolors; NUMA *nag; PROCNAME("pixcmapGammaTRC"); if (!cmap) return ERROR_INT("cmap not defined", procName, 1); if (gamma <= 0.0) { L_WARNING("gamma must be > 0.0; setting to 1.0", procName); gamma = 1.0; } if (minval >= maxval) return ERROR_INT("minval not < maxval", procName, 1); if (gamma == 1.0 && minval == 0 && maxval == 255) /* no-op */ return 0; if ((nag = numaGammaTRC(gamma, minval, maxval)) == NULL) return ERROR_INT("nag not made", procName, 1); ncolors = pixcmapGetCount(cmap); for (i = 0; i < ncolors; i++) { pixcmapGetColor(cmap, i, &rval, &gval, &bval); numaGetIValue(nag, rval, &trval); numaGetIValue(nag, gval, &tgval); numaGetIValue(nag, bval, &tbval); pixcmapResetColor(cmap, i, trval, tgval, tbval); } numaDestroy(&nag); return 0; }
int main(int argc, char **argv) { l_uint8 *array1, *array2; l_int32 n1, n2, n3; size_t size1, size2; FILE *fp; BOXA *boxa1, *boxa2; PIX *pixs, *pix1; PIXA *pixa1; PIXCMAP *cmap; L_REGPARAMS *rp; if (regTestSetup(argc, argv, &rp)) return 1; pixs = pixRead("feyn.tif"); /* --------------------------------------------------------------- * * Test pixConnComp() and pixCountConnComp(), * * with output to both boxa and pixa * * --------------------------------------------------------------- */ /* First, test with 4-cc */ boxa1= pixConnComp(pixs, &pixa1, 4); n1 = boxaGetCount(boxa1); boxa2= pixConnComp(pixs, NULL, 4); n2 = boxaGetCount(boxa2); pixCountConnComp(pixs, 4, &n3); fprintf(stderr, "Number of 4 c.c.: n1 = %d; n2 = %d, n3 = %d\n", n1, n2, n3); regTestCompareValues(rp, n1, n2, 0); /* 0 */ regTestCompareValues(rp, n1, n3, 0); /* 1 */ regTestCompareValues(rp, n1, 4452, 0); /* 2 */ pix1 = pixaDisplay(pixa1, pixGetWidth(pixs), pixGetHeight(pixs)); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 3 */ regTestComparePix(rp, pixs, pix1); /* 4 */ pixaDestroy(&pixa1); boxaDestroy(&boxa1); boxaDestroy(&boxa2); pixDestroy(&pix1); /* Test with 8-cc */ boxa1= pixConnComp(pixs, &pixa1, 8); n1 = boxaGetCount(boxa1); boxa2= pixConnComp(pixs, NULL, 8); n2 = boxaGetCount(boxa2); pixCountConnComp(pixs, 8, &n3); fprintf(stderr, "Number of 8 c.c.: n1 = %d; n2 = %d, n3 = %d\n", n1, n2, n3); regTestCompareValues(rp, n1, n2, 0); /* 5 */ regTestCompareValues(rp, n1, n3, 0); /* 6 */ regTestCompareValues(rp, n1, 4305, 0); /* 7 */ pix1 = pixaDisplay(pixa1, pixGetWidth(pixs), pixGetHeight(pixs)); regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 8 */ regTestComparePix(rp, pixs, pix1); /* 9 */ pixaDestroy(&pixa1); boxaDestroy(&boxa1); boxaDestroy(&boxa2); pixDestroy(&pix1); /* --------------------------------------------------------------- * * Test boxa I/O * * --------------------------------------------------------------- */ lept_mkdir("lept/conn"); boxa1 = pixConnComp(pixs, NULL, 4); fp = lept_fopen("/tmp/lept/conn/boxa1.ba", "wb+"); boxaWriteStream(fp, boxa1); lept_fclose(fp); fp = lept_fopen("/tmp/lept/conn/boxa1.ba", "rb"); boxa2 = boxaReadStream(fp); lept_fclose(fp); fp = lept_fopen("/tmp/lept/conn/boxa2.ba", "wb+"); boxaWriteStream(fp, boxa2); lept_fclose(fp); array1 = l_binaryRead("/tmp/lept/conn/boxa1.ba", &size1); array2 = l_binaryRead("/tmp/lept/conn/boxa2.ba", &size2); regTestCompareStrings(rp, array1, size1, array2, size2); /* 10 */ lept_free(array1); lept_free(array2); boxaDestroy(&boxa1); boxaDestroy(&boxa2); /* --------------------------------------------------------------- * * Just for fun, display each component as a random color in * * cmapped 8 bpp. Background is color 0; it is set to white. * * --------------------------------------------------------------- */ boxa1 = pixConnComp(pixs, &pixa1, 4); pix1 = pixaDisplayRandomCmap(pixa1, pixGetWidth(pixs), pixGetHeight(pixs)); cmap = pixGetColormap(pix1); pixcmapResetColor(cmap, 0, 255, 255, 255); /* reset background to white */ regTestWritePixAndCheck(rp, pix1, IFF_PNG); /* 11 */ if (rp->display) pixDisplay(pix1, 100, 100); boxaDestroy(&boxa1); pixDestroy(&pix1); pixaDestroy(&pixa1); pixDestroy(&pixs); return regTestCleanup(rp); }
int main(int argc, char **argv) { char *filein; l_int32 i, n, count; BOX *box; BOXA *boxa; PIX *pixs, *pixd; PIXA *pixa; PIXCMAP *cmap; static char mainName[] = "cctest1"; if (argc != 2) return ERROR_INT(" Syntax: cctest1 filein", mainName, 1); filein = argv[1]; if ((pixs = pixRead(filein)) == NULL) return ERROR_INT("pixs not made", mainName, 1); if (pixGetDepth(pixs) != 1) exit(ERROR_INT("pixs not 1 bpp", mainName, 1)); /* Test speed of pixCountConnComp() */ startTimer(); for (i = 0; i < NTIMES; i++) pixCountConnComp(pixs, 4, &count); fprintf(stderr, "Time to compute 4-cc: %6.3f sec\n", stopTimer()/NTIMES); fprintf(stderr, "Number of 4-cc: %d\n", count); startTimer(); for (i = 0; i < NTIMES; i++) pixCountConnComp(pixs, 8, &count); fprintf(stderr, "Time to compute 8-cc: %6.3f sec\n", stopTimer()/NTIMES); fprintf(stderr, "Number of 8-cc: %d\n", count); /* Test speed of pixConnComp(), with only boxa output */ startTimer(); for (i = 0; i < NTIMES; i++) { boxa = pixConnComp(pixs, NULL, 4); boxaDestroy(&boxa); } fprintf(stderr, "Time to compute 4-cc: %6.3f sec\n", stopTimer()/NTIMES); startTimer(); for (i = 0; i < NTIMES; i++) { boxa = pixConnComp(pixs, NULL, 8); boxaDestroy(&boxa); } fprintf(stderr, "Time to compute 8-cc: %6.3f sec\n", stopTimer()/NTIMES); /* Draw outline of each c.c. box */ boxa = pixConnComp(pixs, NULL, 4); n = boxaGetCount(boxa); fprintf(stderr, "Num 4-cc boxes: %d\n", n); for (i = 0; i < n; i++) { box = boxaGetBox(boxa, i, L_CLONE); pixRenderBox(pixs, box, 3, L_FLIP_PIXELS); boxDestroy(&box); /* remember, clones need to be destroyed */ } pixDisplayWrite(pixs, 1); boxaDestroy(&boxa); /* Display each component as a random color in cmapped 8 bpp. * Background is color 0; it is set to white. */ boxa = pixConnComp(pixs, &pixa, 4); pixd = pixaDisplayRandomCmap(pixa, pixGetWidth(pixs), pixGetHeight(pixs)); cmap = pixGetColormap(pixd); pixcmapResetColor(cmap, 0, 255, 255, 255); /* reset background to white */ pixDisplay(pixd, 100, 100); pixDisplayWrite(pixd, 1); boxaDestroy(&boxa); pixDestroy(&pixd); pixaDestroy(&pixa); pixDestroy(&pixs); return 0; }
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; }
/*! * \brief pixColorSegmentTryCluster() * * \param[in] pixd * \param[in] pixs * \param[in] maxdist * \param[in] maxcolors * \param[in] debugflag 1 for debug output; 0 otherwise * \return 0 if OK, 1 on error * * <pre> * Notes: * This function should only be called from pixColorSegCluster() * </pre> */ static l_int32 pixColorSegmentTryCluster(PIX *pixd, PIX *pixs, l_int32 maxdist, l_int32 maxcolors, l_int32 debugflag) { l_int32 rmap[256], gmap[256], bmap[256]; l_int32 w, h, wpls, wpld, i, j, k, found, ret, index, ncolors; l_int32 rval, gval, bval, dist2, maxdist2; l_int32 countarray[256]; l_int32 rsum[256], gsum[256], bsum[256]; l_uint32 *ppixel; l_uint32 *datas, *datad, *lines, *lined; PIXCMAP *cmap; PROCNAME("pixColorSegmentTryCluster"); if (!pixs) return ERROR_INT("pixs not defined", procName, 1); if (!pixd) return ERROR_INT("pixd not defined", procName, 1); w = pixGetWidth(pixs); h = pixGetHeight(pixs); maxdist2 = maxdist * maxdist; cmap = pixGetColormap(pixd); pixcmapClear(cmap); for (k = 0; k < 256; k++) { rsum[k] = gsum[k] = bsum[k] = 0; rmap[k] = gmap[k] = bmap[k] = 0; } datas = pixGetData(pixs); datad = pixGetData(pixd); wpls = pixGetWpl(pixs); wpld = pixGetWpl(pixd); ncolors = 0; for (i = 0; i < h; i++) { lines = datas + i * wpls; lined = datad + i * wpld; for (j = 0; j < w; j++) { ppixel = lines + j; rval = GET_DATA_BYTE(ppixel, COLOR_RED); gval = GET_DATA_BYTE(ppixel, COLOR_GREEN); bval = GET_DATA_BYTE(ppixel, COLOR_BLUE); ncolors = pixcmapGetCount(cmap); found = FALSE; for (k = 0; k < ncolors; k++) { dist2 = (rval - rmap[k]) * (rval - rmap[k]) + (gval - gmap[k]) * (gval - gmap[k]) + (bval - bmap[k]) * (bval - bmap[k]); if (dist2 <= maxdist2) { /* take it; greedy */ found = TRUE; SET_DATA_BYTE(lined, j, k); countarray[k]++; rsum[k] += rval; gsum[k] += gval; bsum[k] += bval; break; } } if (!found) { /* Add a new color */ ret = pixcmapAddNewColor(cmap, rval, gval, bval, &index); /* fprintf(stderr, "index = %d, (i,j) = (%d,%d), rgb = (%d, %d, %d)\n", index, i, j, rval, gval, bval); */ if (ret == 0 && index < maxcolors) { countarray[index] = 1; SET_DATA_BYTE(lined, j, index); rmap[index] = rval; gmap[index] = gval; bmap[index] = bval; rsum[index] = rval; gsum[index] = gval; bsum[index] = bval; } else { if (debugflag) { L_INFO("maxcolors exceeded for maxdist = %d\n", procName, maxdist); } return 1; } } } } /* Replace the colors in the colormap by the averages */ for (k = 0; k < ncolors; k++) { rval = rsum[k] / countarray[k]; gval = gsum[k] / countarray[k]; bval = bsum[k] / countarray[k]; pixcmapResetColor(cmap, k, rval, gval, bval); } return 0; }
/*! * pixGetRegionsBinary() * * Input: pixs (1 bpp, assumed to be 300 to 400 ppi) * &pixhm (<optional return> halftone mask) * &pixtm (<optional return> textline mask) * &pixtb (<optional return> textblock mask) * debug (flag: set to 1 for debug output) * Return: 0 if OK, 1 on error * * Notes: * (1) It is best to deskew the image before segmenting. * (2) The debug flag enables a number of outputs. These * are included to show how to generate and save/display * these results. */ l_int32 pixGetRegionsBinary(PIX *pixs, PIX **ppixhm, PIX **ppixtm, PIX **ppixtb, l_int32 debug) { char *tempname; l_int32 htfound, tlfound; PIX *pixr, *pixt1, *pixt2; PIX *pixtext; /* text pixels only */ PIX *pixhm2; /* halftone mask; 2x reduction */ PIX *pixhm; /* halftone mask; */ PIX *pixtm2; /* textline mask; 2x reduction */ PIX *pixtm; /* textline mask */ PIX *pixvws; /* vertical white space mask */ PIX *pixtb2; /* textblock mask; 2x reduction */ PIX *pixtbf2; /* textblock mask; 2x reduction; small comps filtered */ PIX *pixtb; /* textblock mask */ PROCNAME("pixGetRegionsBinary"); if (ppixhm) *ppixhm = NULL; if (ppixtm) *ppixtm = NULL; if (ppixtb) *ppixtb = NULL; if (!pixs) return ERROR_INT("pixs not defined", procName, 1); if (pixGetDepth(pixs) != 1) return ERROR_INT("pixs not 1 bpp", procName, 1); /* 2x reduce, to 150 -200 ppi */ pixr = pixReduceRankBinaryCascade(pixs, 1, 0, 0, 0); pixDisplayWrite(pixr, debug); /* Get the halftone mask */ pixhm2 = pixGenHalftoneMask(pixr, &pixtext, &htfound, debug); /* Get the textline mask from the text pixels */ pixtm2 = pixGenTextlineMask(pixtext, &pixvws, &tlfound, debug); /* Get the textblock mask from the textline mask */ pixtb2 = pixGenTextblockMask(pixtm2, pixvws, debug); pixDestroy(&pixr); pixDestroy(&pixtext); pixDestroy(&pixvws); /* Remove small components from the mask, where a small * component is defined as one with both width and height < 60 */ pixtbf2 = pixSelectBySize(pixtb2, 60, 60, 4, L_SELECT_IF_EITHER, L_SELECT_IF_GTE, NULL); pixDestroy(&pixtb2); pixDisplayWriteFormat(pixtbf2, debug, IFF_PNG); /* Expand all masks to full resolution, and do filling or * small dilations for better coverage. */ pixhm = pixExpandReplicate(pixhm2, 2); pixt1 = pixSeedfillBinary(NULL, pixhm, pixs, 8); pixOr(pixhm, pixhm, pixt1); pixDestroy(&pixt1); pixDisplayWriteFormat(pixhm, debug, IFF_PNG); pixt1 = pixExpandReplicate(pixtm2, 2); pixtm = pixDilateBrick(NULL, pixt1, 3, 3); pixDestroy(&pixt1); pixDisplayWriteFormat(pixtm, debug, IFF_PNG); pixt1 = pixExpandReplicate(pixtbf2, 2); pixtb = pixDilateBrick(NULL, pixt1, 3, 3); pixDestroy(&pixt1); pixDisplayWriteFormat(pixtb, debug, IFF_PNG); pixDestroy(&pixhm2); pixDestroy(&pixtm2); pixDestroy(&pixtbf2); /* Debug: identify objects that are neither text nor halftone image */ if (debug) { pixt1 = pixSubtract(NULL, pixs, pixtm); /* remove text pixels */ pixt2 = pixSubtract(NULL, pixt1, pixhm); /* remove halftone pixels */ pixDisplayWriteFormat(pixt2, 1, IFF_PNG); pixDestroy(&pixt1); pixDestroy(&pixt2); } /* Debug: display textline components with random colors */ if (debug) { l_int32 w, h; BOXA *boxa; PIXA *pixa; boxa = pixConnComp(pixtm, &pixa, 8); pixGetDimensions(pixtm, &w, &h, NULL); pixt1 = pixaDisplayRandomCmap(pixa, w, h); pixcmapResetColor(pixGetColormap(pixt1), 0, 255, 255, 255); pixDisplay(pixt1, 100, 100); pixDisplayWriteFormat(pixt1, 1, IFF_PNG); pixaDestroy(&pixa); boxaDestroy(&boxa); pixDestroy(&pixt1); } /* Debug: identify the outlines of each textblock */ if (debug) { PIXCMAP *cmap; PTAA *ptaa; ptaa = pixGetOuterBordersPtaa(pixtb); tempname = genTempFilename("/tmp", "tb_outlines.ptaa", 0, 0); ptaaWrite(tempname, ptaa, 1); FREE(tempname); pixt1 = pixRenderRandomCmapPtaa(pixtb, ptaa, 1, 16, 1); cmap = pixGetColormap(pixt1); pixcmapResetColor(cmap, 0, 130, 130, 130); pixDisplay(pixt1, 500, 100); pixDisplayWriteFormat(pixt1, 1, IFF_PNG); pixDestroy(&pixt1); ptaaDestroy(&ptaa); } /* Debug: get b.b. for all mask components */ if (debug) { BOXA *bahm, *batm, *batb; bahm = pixConnComp(pixhm, NULL, 4); batm = pixConnComp(pixtm, NULL, 4); batb = pixConnComp(pixtb, NULL, 4); tempname = genTempFilename("/tmp", "htmask.boxa", 0, 0); boxaWrite(tempname, bahm); FREE(tempname); tempname = genTempFilename("/tmp", "textmask.boxa", 0, 0); boxaWrite(tempname, batm); FREE(tempname); tempname = genTempFilename("/tmp", "textblock.boxa", 0, 0); boxaWrite(tempname, batb); FREE(tempname); boxaDestroy(&bahm); boxaDestroy(&batm); boxaDestroy(&batb); } if (ppixhm) *ppixhm = pixhm; else pixDestroy(&pixhm); if (ppixtm) *ppixtm = pixtm; else pixDestroy(&pixtm); if (ppixtb) *ppixtb = pixtb; else pixDestroy(&pixtb); return 0; }
l_int32 main(int argc, char **argv) { char buf[512]; l_int32 i, n, index; l_int32 rval[4], gval[4], bval[4]; l_uint32 scolor, dcolor; L_BMF *bmf; PIX *pix0, *pix1, *pix2, *pix3, *pix4, *pix5; PIXA *pixa; PIXCMAP *cmap; L_REGPARAMS *rp; if (regTestSetup(argc, argv, &rp)) return 1; /* Read in the bg colors */ for (i = 0; i < 4; i++) sscanf(bgcolors[i], "%d %d %d", &rval[i], &gval[i], &bval[i]); bmf = bmfCreate("fonts", 8); /* Get the input image (100 ppi resolution) */ pix0 = pixRead("harmoniam100-11.png"); cmap = pixGetColormap(pix0); pixa = pixaCreate(0); /* Do cmapped coloring on the white pixels only */ pixcmapGetIndex(cmap, 255, 255, 255, &index); /* index of white pixels */ for (i = 0; i < 4; i++) { pixcmapResetColor(cmap, index, rval[i], gval[i], bval[i]); snprintf(buf, sizeof(buf), "(rval, bval, gval) = (%d, %d, %d)", rval[i], gval[i], bval[i]); pix1 = pixAddSingleTextblock(pix0, bmf, buf, 0xff000000, L_ADD_AT_BOT, NULL); pixaAddPix(pixa, pix1, L_INSERT); } /* Do cmapped background coloring on all the pixels */ for (i = 0; i < 4; i++) { scolor = 0xffffff00; /* source color */ composeRGBPixel(rval[i], gval[i], bval[i], &dcolor); /* dest color */ pix1 = pixShiftByComponent(NULL, pix0, scolor, dcolor); snprintf(buf, sizeof(buf), "(rval, bval, gval) = (%d, %d, %d)", rval[i], gval[i], bval[i]); pix2 = pixAddSingleTextblock(pix1, bmf, buf, 0xff000000, L_ADD_AT_BOT, NULL); pixaAddPix(pixa, pix2, L_INSERT); pixDestroy(&pix1); } /* Do background coloring on rgb */ pix1 = pixConvertTo32(pix0); for (i = 0; i < 4; i++) { scolor = 0xffffff00; composeRGBPixel(rval[i], gval[i], bval[i], &dcolor); pix2 = pixShiftByComponent(NULL, pix1, scolor, dcolor); snprintf(buf, sizeof(buf), "(rval, bval, gval) = (%d, %d, %d)", rval[i], gval[i], bval[i]); pix3 = pixAddSingleTextblock(pix2, bmf, buf, 0xff000000, L_ADD_AT_BOT, NULL); pixaAddPix(pixa, pix3, L_INSERT); pixDestroy(&pix2); } pixDestroy(&pix1); /* Compare cmapped & rgb foreground coloring */ scolor = 0x0; /* source color */ composeRGBPixel(200, 30, 150, &dcolor); /* ugly fg dest color */ pix1 = pixShiftByComponent(NULL, pix0, scolor, dcolor); /* cmapped */ snprintf(buf, sizeof(buf), "(rval, bval, gval) = (%d, %d, %d)", 200, 100, 50); pix2 = pixAddSingleTextblock(pix1, bmf, buf, 0xff000000, L_ADD_AT_BOT, NULL); pixaAddPix(pixa, pix2, L_INSERT); pix3 = pixConvertTo32(pix0); pix4 = pixShiftByComponent(NULL, pix3, scolor, dcolor); /* rgb */ snprintf(buf, sizeof(buf), "(rval, bval, gval) = (%d, %d, %d)", 200, 100, 50); pix5 = pixAddSingleTextblock(pix4, bmf, buf, 0xff000000, L_ADD_AT_BOT, NULL); pixaAddPix(pixa, pix5, L_INSERT); regTestComparePix(rp, pix1, pix4); regTestComparePix(rp, pix2, pix5); pixDestroy(&pix1); pixDestroy(&pix3); pixDestroy(&pix4); /* Log all the results */ n = pixaGetCount(pixa); for (i = 0; i < n; i++) { pix1 = pixaGetPix(pixa, i, L_CLONE); regTestWritePixAndCheck(rp, pix1, IFF_PNG); pixDestroy(&pix1); } /* If in testing mode, make a pdf */ if (rp->display) { pixaConvertToPdf(pixa, 100, 1.0, L_FLATE_ENCODE, 0, "Colored background", "/tmp/regout/coloring.pdf"); L_INFO("Output pdf: /tmp/regout/coloring.pdf\n", rp->testname); } pixaDestroy(&pixa); pixDestroy(&pix0); bmfDestroy(&bmf); return regTestCleanup(rp); }
l_int32 main(int argc, char **argv) { l_int32 index; PIX *pixs, *pixc, *pixd; PIXCMAP *cmap; L_REGPARAMS *rp; if (regTestSetup(argc, argv, &rp)) return 1; fprintf(stderr, "Test binary image:\n"); pixs = pixRead(BINARY_IMAGE); pixd = shearTest(pixs, 1); regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 0 */ pixDisplayWithTitle(pixd, 100, 100, NULL, rp->display); pixDestroy(&pixs); pixDestroy(&pixd); /* We change the black to dark red so that we can see * that the IP shear does brings in that color. It * can't bring in black because the cmap is filled. */ fprintf(stderr, "Test 2 bpp cmapped image with filled cmap:\n"); pixs = pixRead(TWO_BPP_IMAGE); cmap = pixGetColormap(pixs); pixcmapGetIndex(cmap, 40, 44, 40, &index); pixcmapResetColor(cmap, index, 100, 0, 0); pixd = shearTest(pixs, 1); regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 1 */ pixDisplayWithTitle(pixd, 100, 100, NULL, rp->display); pixDestroy(&pixs); pixDestroy(&pixd); fprintf(stderr, "Test 4 bpp cmapped image with unfilled cmap:\n"); pixs = pixRead(FOUR_BPP_IMAGE1); pixd = shearTest(pixs, 1); regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 2 */ pixDisplayWithTitle(pixd, 100, 100, NULL, rp->display); pixDestroy(&pixs); pixDestroy(&pixd); fprintf(stderr, "Test 4 bpp cmapped image with filled cmap:\n"); pixs = pixRead(FOUR_BPP_IMAGE2); pixd = shearTest(pixs, 1); regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 3 */ pixDisplayWithTitle(pixd, 100, 100, NULL, rp->display); pixDestroy(&pixs); pixDestroy(&pixd); fprintf(stderr, "Test 8 bpp grayscale image:\n"); pixs = pixRead(EIGHT_BPP_IMAGE); pixd = shearTest(pixs, 2); regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG); /* 4 */ pixDisplayWithTitle(pixd, 100, 100, NULL, rp->display); pixDestroy(&pixs); pixDestroy(&pixd); fprintf(stderr, "Test 8 bpp grayscale cmap image:\n"); pixs = pixRead(EIGHT_BPP_CMAP_IMAGE1); pixd = shearTest(pixs, 1); regTestWritePixAndCheck(rp, pixd, IFF_PNG); /* 5 */ pixDisplayWithTitle(pixd, 100, 100, NULL, rp->display); pixDestroy(&pixs); pixDestroy(&pixd); fprintf(stderr, "Test 8 bpp color cmap image:\n"); pixs = pixRead(EIGHT_BPP_CMAP_IMAGE2); pixd = pixOctreeColorQuant(pixs, 200, 0); pixc = shearTest(pixd, 3); regTestWritePixAndCheck(rp, pixc, IFF_JFIF_JPEG); /* 6 */ pixDisplayWithTitle(pixc, 100, 100, NULL, rp->display); pixDestroy(&pixs); pixDestroy(&pixd); pixDestroy(&pixc); fprintf(stderr, "Test rgb image:\n"); pixs = pixRead(RGB_IMAGE); pixd = shearTest(pixs, 2); regTestWritePixAndCheck(rp, pixd, IFF_JFIF_JPEG); /* 7 */ pixDisplayWithTitle(pixd, 100, 100, NULL, rp->display); pixDestroy(&pixs); pixDestroy(&pixd); return regTestCleanup(rp); }
main(int argc, char **argv) { l_int32 w, h; BOXA *boxa; PIX *pixs, *pixt1, *pixt2, *pixg, *pixb, *pixd, *pixc; PIX *pixm, *pixm2, *pixd2, *pixs2; PIXA *pixa, *pixac; PIXCMAP *cmap, *cmapg; static char mainName[] = "misctest1"; pixac = pixaCreate(0); /* Combine two grayscale images using a mask */ pixd = pixRead("feyn.tif"); pixs = pixRead("rabi.png"); pixm = pixRead("pageseg2-seed.png"); pixd2 = pixScaleToGray2(pixd); pixs2 = pixScaleToGray2(pixs); pixSaveTiled(pixd2, pixac, 2, 1, 40, 32); pixSaveTiled(pixs2, pixac, 2, 0, 40, 0); pixSaveTiled(pixm, pixac, 2, 0, 40, 0); pixCombineMaskedGeneral(pixd2, pixs2, pixm, 100, 100); pixSaveTiled(pixd2, pixac, 2, 1, 40, 0); pixDisplayWithTitle(pixd2, 100, 100, NULL, SHOW); pixDestroy(&pixd2); pixDestroy(&pixs2); /* Combine two binary images using a mask */ pixm2 = pixExpandBinaryReplicate(pixm, 2); pixt1 = pixCopy(NULL, pixd); pixCombineMaskedGeneral(pixd, pixs, pixm2, 200, 200); pixSaveTiled(pixd, pixac, 4, 0, 40, 0); pixDisplayWithTitle(pixd, 700, 100, NULL, SHOW); pixCombineMasked(pixt1, pixs, pixm2); pixSaveTiled(pixt1, pixac, 4, 0, 40, 0); pixDestroy(&pixd); pixDestroy(&pixt1); pixDestroy(&pixs); pixDestroy(&pixm); pixDestroy(&pixm2); /* Do a restricted seedfill */ pixs = pixRead("pageseg2-seed.png"); pixm = pixRead("pageseg2-mask.png"); pixd = pixSeedfillBinaryRestricted(NULL, pixs, pixm, 8, 50, 175); pixSaveTiled(pixs, pixac, 2, 1, 40, 0); pixSaveTiled(pixm, pixac, 2, 0, 40, 0); pixSaveTiled(pixd, pixac, 2, 0, 40, 0); pixDestroy(&pixs); pixDestroy(&pixm); pixDestroy(&pixd); /* Colorize a grayscale image */ pixs = pixRead("lucasta.150.jpg"); pixGetDimensions(pixs, &w, &h, NULL); pixb = pixThresholdToBinary(pixs, 128); boxa = pixConnComp(pixb, &pixa, 8); pixSaveTiled(pixs, pixac, 1, 1, 40, 0); cmap = pixcmapGrayToColor(0x6f90c0); pixSetColormap(pixs, cmap); pixSaveTiled(pixs, pixac, 1, 0, 40, 0); pixc = pixaDisplayRandomCmap(pixa, w, h); pixcmapResetColor(pixGetColormap(pixc), 0, 255, 255, 255); pixSaveTiled(pixc, pixac, 1, 0, 40, 0); pixDestroy(&pixs); pixDestroy(&pixb); pixDestroy(&pixc); boxaDestroy(&boxa); pixaDestroy(&pixa); /* Convert color to gray */ pixs = pixRead("weasel4.16c.png"); pixSaveTiled(pixs, pixac, 1, 1, 20, 0); pixc = pixConvertTo32(pixs); pixt1 = pixConvertRGBToGray(pixc, 3., 7., 5.); pixSaveTiled(pixt1, pixac, 1, 0, 20, 0); pixt2 = pixConvertRGBToGrayFast(pixc); pixSaveTiled(pixt2, pixac, 1, 0, 20, 0); pixg = pixCopy(NULL, pixs); cmap = pixGetColormap(pixs); cmapg = pixcmapColorToGray(cmap, 4., 6., 3.); pixSetColormap(pixg, cmapg); pixSaveTiled(pixg, pixac, 1, 0, 20, 0); pixDestroy(&pixs); pixDestroy(&pixc); pixDestroy(&pixt1); pixDestroy(&pixt2); pixDestroy(&pixg); pixd = pixaDisplay(pixac, 0, 0); pixDisplayWithTitle(pixd, 100, 100, NULL, 1); pixWrite("junkmisc1.png", pixd, IFF_PNG); pixDestroy(&pixd); pixaDestroy(&pixac); return 0; }
main(int argc, char **argv) { l_uint8 *array1, *array2; l_int32 i, n, np, same, diff, nbytes1, nbytes2; FILE *fp; BOX *box; BOXA *boxa, *boxa2; PIX *pixs, *pixd; PIXA *pixa; PIXCMAP *cmap; static char mainName[] = "conncomp_reg"; if (argc != 1) exit(ERROR_INT(" Syntax: conncomp_reg", mainName, 1)); if ((pixs = pixRead("feyn.tif")) == NULL) exit(ERROR_INT("pixs not made", mainName, 1)); /* Test pixConnComp() with output to both boxa and pixa */ /* First, test with 4-cc */ boxa = pixConnComp(pixs, &pixa, 4); n = boxaGetCount(boxa); fprintf(stderr, "Number of 4 c.c. b.b: %d\n", n); np = pixaGetCount(pixa); fprintf(stderr, "Number of 4 c.c. pix: %d\n", np); pixd = pixaDisplay(pixa, pixGetWidth(pixs), pixGetHeight(pixs)); pixWrite("/tmp/junkout1.png", pixd, IFF_PNG); pixEqual(pixs, pixd, &same); if (same == 1) fprintf(stderr, "Source and reconstructed pix are the same.\n"); else fprintf(stderr, "Error: source and reconstructed pix differ!\n"); pixaDestroy(&pixa); boxaDestroy(&boxa); pixDestroy(&pixd); /* Test with 8-cc */ boxa = pixConnComp(pixs, &pixa, 8); n = boxaGetCount(boxa); fprintf(stderr, "Number of 8 c.c. b.b: %d\n", n); np = pixaGetCount(pixa); fprintf(stderr, "Number of 8 c.c. pix: %d\n", np); pixd = pixaDisplay(pixa, pixGetWidth(pixs), pixGetHeight(pixs)); pixWrite("/tmp/junkout2.png", pixd, IFF_PNG); pixEqual(pixs, pixd, &same); if (same == 1) fprintf(stderr, "Source and reconstructed pix are the same.\n"); else fprintf(stderr, "Error: source and reconstructed pix differ!\n"); pixaDestroy(&pixa); boxaDestroy(&boxa); pixDestroy(&pixd); /* Test i/o */ boxa = pixConnComp(pixs, NULL, 4); fp = fopen("/tmp/junk1.ba", "wb+"); boxaWriteStream(fp, boxa); fclose(fp); fp = fopen("/tmp/junk1.ba", "r"); boxa2 = boxaReadStream(fp); fclose(fp); fp = fopen("/tmp/junk2.ba", "wb+"); boxaWriteStream(fp, boxa2); fclose(fp); array1 = arrayRead("/tmp/junk1.ba", &nbytes1); array2 = arrayRead("/tmp/junk2.ba", &nbytes2); diff = strcmp((char *)array1, (char *)array2); if (nbytes1 != nbytes2 || diff) fprintf(stderr, "I/O error for boxes.\n"); else fprintf(stderr, "I/O valid for boxes.\n"); FREE(array1); FREE(array2); boxaDestroy(&boxa); boxaDestroy(&boxa2); /* Just for fun, display each component as a random color * in cmapped 8 bpp. Background is color 0; it is set to white. */ boxa = pixConnComp(pixs, &pixa, 4); pixd = pixaDisplayRandomCmap(pixa, pixGetWidth(pixs), pixGetHeight(pixs)); cmap = pixGetColormap(pixd); pixcmapResetColor(cmap, 0, 255, 255, 255); /* reset background to white */ pixDisplay(pixd, 100, 100); boxaDestroy(&boxa); pixDestroy(&pixd); pixaDestroy(&pixa); pixDestroy(&pixs); exit(0); }
main(int argc, char **argv) { l_int32 ws, hs; BOX *box; BOXA *boxa; PIX *pixs, *pixc, *pix32, *pixt, *pixd; PIXA *pixat, *pixas, *pixac; static char mainName[] = "pixadisp_reg"; if (argc != 1) exit(ERROR_INT(" Syntax: pixadisp_reg", mainName, 1)); if ((pixs = pixRead("feyn.tif")) == NULL) exit(ERROR_INT("pixs not made", mainName, 1)); box = boxCreate(683, 799, 970, 479); pixc = pixClipRectangle(pixs, box, NULL); boxDestroy(&box); pixDisplayWrite(pixc, 1); if ((pix32 = pixRead("marge.jpg")) == NULL) exit(ERROR_INT("pix32 not made", mainName, 1)); /* Generate pixas from pixs and pixac from pixc */ boxa = pixConnComp(pixs, &pixat, 8); pixas = pixaSelectBySize(pixat, 60, 60, L_SELECT_IF_BOTH, L_SELECT_IF_LTE, NULL); pixaDestroy(&pixat); boxaDestroy(&boxa); boxa = pixConnComp(pixc, &pixac, 8); boxaDestroy(&boxa); /* pixaDisplay() */ pixGetDimensions(pixs, &ws, &hs, NULL); pixd = pixaDisplay(pixas, ws, hs); pixDisplayWrite(pixd, 1); pixDestroy(&pixd); /* pixaDisplayRandomCmap() */ pixd = pixaDisplayRandomCmap(pixas, ws, hs); /* black bg */ pixDisplayWrite(pixd, 1); pixcmapResetColor(pixGetColormap(pixd), 0, 255, 255, 255); /* white bg */ pixDisplayWrite(pixd, 1); pixDestroy(&pixd); /* pixaDisplayOnLattice() */ pixd = pixaDisplayOnLattice(pixac, 50, 50); pixDisplayWrite(pixd, 1); pixDestroy(&pixd); /* pixaDisplayUnsplit() */ pixat = pixaSplitPix(pix32, 5, 7, 10, 0x0000ff00); pixd = pixaDisplayUnsplit(pixat, 5, 7, 10, 0x00ff0000); pixDisplayWrite(pixd, 1); pixaDestroy(&pixat); pixDestroy(&pixd); /* pixaDisplayTiled() */ pixd = pixaDisplayTiled(pixac, 1000, 0, 10); pixDisplayWrite(pixd, 1); pixDestroy(&pixd); /* pixaDisplayTiledInRows() */ pixd = pixaDisplayTiledInRows(pixac, 1, 1000, 1.0, 0, 10, 2); pixDisplayWrite(pixd, 1); pixDestroy(&pixd); /* pixaDisplayTiledAndScaled() */ pixd = pixaDisplayTiledAndScaled(pixac, 1, 25, 20, 0, 5, 0); pixDisplayWrite(pixd, 1); pixDestroy(&pixd); pixat = pixaCreate(10); pixd = pixRankFilter(pix32, 8, 8, 0.5); pixaAddPix(pixat, pixd, L_INSERT); pixt = pixScale(pix32, 0.5, 0.5); pixd = pixRankFilter(pixt, 8, 8, 0.5); pixaAddPix(pixat, pixd, L_INSERT); pixDestroy(&pixt); pixt = pixScale(pix32, 0.25, 0.25); pixd = pixRankFilter(pixt, 8, 8, 0.5); pixaAddPix(pixat, pixd, L_INSERT); pixDestroy(&pixt); pixd = pixaDisplayTiledAndScaled(pixat, 32, 500, 1, 0, 25, 0); pixDisplayWrite(pixd, 1); pixaDestroy(&pixat); pixDestroy(&pixd); pixaDestroy(&pixas); pixaDestroy(&pixac); pixDestroy(&pixs); pixDestroy(&pixc); pixDestroy(&pix32); pixDisplayMultiple("/tmp/junk_write_display*"); return 0; }