/*! * pixCloseGray3() * * Input: pixs (8 bpp, not cmapped) * hsize (1 or 3) * vsize (1 or 3) * Return: pixd, or null on error * * Notes: * (1) Special case for 1x3, 3x1 or 3x3 brick sel (all hits) * (2) If hsize = vsize = 1, just returns a copy. */ PIX * pixCloseGray3(PIX *pixs, l_int32 hsize, l_int32 vsize) { PIX *pixt, *pixb, *pixbd, *pixd; PROCNAME("pixCloseGray3"); if (!pixs) return (PIX *)ERROR_PTR("pixs not defined", procName, NULL); if (pixGetDepth(pixs) != 8) return (PIX *)ERROR_PTR("pixs not 8 bpp", procName, NULL); if (pixGetColormap(pixs)) return (PIX *)ERROR_PTR("pix has colormap", procName, NULL); if ((hsize != 1 && hsize != 3) || (vsize != 1 && vsize != 3)) return (PIX *)ERROR_PTR("invalid size: must be 1 or 3", procName, NULL); if (hsize == 1 && vsize == 1) return pixCopy(NULL, pixs); pixb = pixAddBorderGeneral(pixs, 4, 8, 2, 8, 0); /* set to min */ if (vsize == 1) { pixt = pixDilateGray3h(pixb); pixSetBorderVal(pixt, 4, 8, 2, 8, 255); /* set to max */ pixbd = pixErodeGray3h(pixt); pixDestroy(&pixt); } else if (hsize == 1) { pixt = pixDilateGray3v(pixb); pixSetBorderVal(pixt, 4, 8, 2, 8, 255); pixbd = pixErodeGray3v(pixt); pixDestroy(&pixt); } else { /* vize == hsize == 3 */ pixt = pixDilateGray3h(pixb); pixbd = pixDilateGray3v(pixt); pixDestroy(&pixt); pixSetBorderVal(pixbd, 4, 8, 2, 8, 255); pixt = pixErodeGray3h(pixbd); pixDestroy(&pixbd); pixbd = pixErodeGray3v(pixt); pixDestroy(&pixt); } pixd = pixRemoveBorderGeneral(pixbd, 4, 8, 2, 8); pixDestroy(&pixb); pixDestroy(&pixbd); return pixd; }
/*! * pixDilateGray3h() * * Input: pixs (8 bpp, not cmapped) * Return: pixd, or null on error * * Notes: * (1) Special case for horizontal 3x1 brick Sel; * also used as the first step for the 3x3 brick Sel. */ static PIX * pixDilateGray3h(PIX *pixs) { l_uint32 *datas, *datad, *lines, *lined; l_int32 w, h, wpl, i, j; l_int32 val0, val1, val2, val3, val4, val5, val6, val7, val8, val9, maxval; PIX *pixd; PROCNAME("pixDilateGray3h"); if (!pixs) return (PIX *)ERROR_PTR("pixs not defined", procName, NULL); if (pixGetDepth(pixs) != 8) return (PIX *)ERROR_PTR("pixs not 8 bpp", procName, NULL); pixd = pixCreateTemplateNoInit(pixs); pixSetBorderVal(pixd, 4, 8, 2, 8, 0); /* only to silence valgrind */ pixGetDimensions(pixs, &w, &h, NULL); datas = pixGetData(pixs); datad = pixGetData(pixd); wpl = pixGetWpl(pixs); for (i = 0; i < h; i++) { lines = datas + i * wpl; lined = datad + i * wpl; for (j = 1; j < w - 8; j += 8) { val0 = GET_DATA_BYTE(lines, j - 1); val1 = GET_DATA_BYTE(lines, j); val2 = GET_DATA_BYTE(lines, j + 1); val3 = GET_DATA_BYTE(lines, j + 2); val4 = GET_DATA_BYTE(lines, j + 3); val5 = GET_DATA_BYTE(lines, j + 4); val6 = GET_DATA_BYTE(lines, j + 5); val7 = GET_DATA_BYTE(lines, j + 6); val8 = GET_DATA_BYTE(lines, j + 7); val9 = GET_DATA_BYTE(lines, j + 8); maxval = L_MAX(val1, val2); SET_DATA_BYTE(lined, j, L_MAX(val0, maxval)); SET_DATA_BYTE(lined, j + 1, L_MAX(maxval, val3)); maxval = L_MAX(val3, val4); SET_DATA_BYTE(lined, j + 2, L_MAX(val2, maxval)); SET_DATA_BYTE(lined, j + 3, L_MAX(maxval, val5)); maxval = L_MAX(val5, val6); SET_DATA_BYTE(lined, j + 4, L_MAX(val4, maxval)); SET_DATA_BYTE(lined, j + 5, L_MAX(maxval, val7)); maxval = L_MAX(val7, val8); SET_DATA_BYTE(lined, j + 6, L_MAX(val6, maxval)); SET_DATA_BYTE(lined, j + 7, L_MAX(maxval, val9)); } } return pixd; }
/*! * \brief boxaDisplayTiled() * * \param[in] boxas * \param[in] pixa [optional] background for each box * \param[in] first index of first box * \param[in] last index of last box; use -1 to go to end * \param[in] maxwidth of output image * \param[in] linewidth width of box outlines, before scaling * \param[in] scalefactor applied to every box; use 1.0 for no scaling * \param[in] background 0 for white, 1 for black; this is the color * of the spacing between the images * \param[in] spacing between images, and on outside * \param[in] border width of black border added to each image; * use 0 for no border * \return pixd of tiled images of boxes, or NULL on error * * <pre> * Notes: * (1) Displays each box separately in a tiled 32 bpp image. * (2) If pixa is defined, it must have the same count as the boxa, * and it will be a background over with each box is rendered. * If pixa is not defined, the boxes will be rendered over * blank images of identical size. * (3) See pixaDisplayTiledInRows() for other parameters. * </pre> */ PIX * boxaDisplayTiled(BOXA *boxas, PIXA *pixa, l_int32 first, l_int32 last, l_int32 maxwidth, l_int32 linewidth, l_float32 scalefactor, l_int32 background, l_int32 spacing, l_int32 border) { char buf[32]; l_int32 i, n, npix, w, h, fontsize; L_BMF *bmf; BOX *box; BOXA *boxa; PIX *pix1, *pix2, *pixd; PIXA *pixat; PROCNAME("boxaDisplayTiled"); if (!boxas) return (PIX *)ERROR_PTR("boxas not defined", procName, NULL); boxa = boxaSaveValid(boxas, L_COPY); n = boxaGetCount(boxa); if (pixa) { npix = pixaGetCount(pixa); if (n != npix) { boxaDestroy(&boxa); return (PIX *)ERROR_PTR("boxa and pixa counts differ", procName, NULL); } } first = L_MAX(0, first); if (last < 0) last = n - 1; if (first >= n) { boxaDestroy(&boxa); return (PIX *)ERROR_PTR("invalid first", procName, NULL); } if (last >= n) { L_WARNING("last = %d is beyond max index = %d; adjusting\n", procName, last, n - 1); last = n - 1; } if (first > last) { boxaDestroy(&boxa); return (PIX *)ERROR_PTR("first > last", procName, NULL); } /* Because the bitmap font will be reduced when tiled, choose the * font size inversely with the scale factor. */ if (scalefactor > 0.8) fontsize = 6; else if (scalefactor > 0.6) fontsize = 10; else if (scalefactor > 0.4) fontsize = 14; else if (scalefactor > 0.3) fontsize = 18; else fontsize = 20; bmf = bmfCreate(NULL, fontsize); pixat = pixaCreate(n); boxaGetExtent(boxa, &w, &h, NULL); for (i = first; i <= last; i++) { box = boxaGetBox(boxa, i, L_CLONE); if (!pixa) { pix1 = pixCreate(w, h, 32); pixSetAll(pix1); } else { pix1 = pixaGetPix(pixa, i, L_COPY); } pixSetBorderVal(pix1, 0, 0, 0, 2, 0x0000ff00); snprintf(buf, sizeof(buf), "%d", i); pix2 = pixAddSingleTextblock(pix1, bmf, buf, 0x00ff0000, L_ADD_BELOW, NULL); pixDestroy(&pix1); pixRenderBoxArb(pix2, box, linewidth, 255, 0, 0); pixaAddPix(pixat, pix2, L_INSERT); boxDestroy(&box); } bmfDestroy(&bmf); boxaDestroy(&boxa); pixd = pixaDisplayTiledInRows(pixat, 32, maxwidth, scalefactor, background, spacing, border); pixaDestroy(&pixat); return pixd; }