/*!
 *  pixColorGrayRegionsCmap()
 *
 *      Input:  pixs (8 bpp, with colormap)
 *              boxa (of regions in which to apply color)
 *              type (L_PAINT_LIGHT, L_PAINT_DARK)
 *              rval, gval, bval (target color)
 *      Return: 0 if OK, 1 on error
 *
 *  Notes:
 *      (1) This is an in-place operation.
 *      (2) If type == L_PAINT_LIGHT, it colorizes non-black pixels,
 *          preserving antialiasing.
 *          If type == L_PAINT_DARK, it colorizes non-white pixels,
 *          preserving antialiasing.  See pixColorGrayCmap() for details.
 *      (3) This can also be called through pixColorGrayRegions().
 *      (4) This increases the colormap size by the number of
 *          different gray (non-black or non-white) colors in the
 *          selected regions of pixs.  If there is not enough room in
 *          the colormap for this expansion, it returns 1 (error),
 *          and the caller should check the return value.
 *      (5) Because two boxes in the boxa can overlap, pixels that
 *          are colorized in the first box must be excluded in the
 *          second because their value exceeds the size of the map.
 */
l_int32
pixColorGrayRegionsCmap(PIX     *pixs,
                        BOXA    *boxa,
                        l_int32  type,
                        l_int32  rval,
                        l_int32  gval,
                        l_int32  bval)
{
l_int32    i, j, k, w, h, n, nc, x1, y1, x2, y2, bw, bh, wpl;
l_int32    val, nval;
l_int32   *map;
l_uint32  *line, *data;
BOX       *box;
NUMA      *na;
PIXCMAP   *cmap;

    PROCNAME("pixColorGrayRegionsCmap");

    if (!pixs)
        return ERROR_INT("pixs not defined", procName, 1);
    if (!boxa)
        return ERROR_INT("boxa not defined", procName, 1);
    if ((cmap = pixGetColormap(pixs)) == NULL)
        return ERROR_INT("no colormap", procName, 1);
    if (pixGetDepth(pixs) != 8)
        return ERROR_INT("depth not 8 bpp", procName, 1);
    if (type != L_PAINT_DARK && type != L_PAINT_LIGHT)
        return ERROR_INT("invalid type", procName, 1);

    nc = pixcmapGetCount(cmap);
    if (addColorizedGrayToCmap(cmap, type, rval, gval, bval, &na))
        return ERROR_INT("no room; cmap full", procName, 1);
    map = numaGetIArray(na);
    numaDestroy(&na);
    if (!map)
        return ERROR_INT("map not made", procName, 1);

    pixGetDimensions(pixs, &w, &h, NULL);
    data = pixGetData(pixs);
    wpl = pixGetWpl(pixs);
    n = boxaGetCount(boxa);
    for (k = 0; k < n; k++) {
        box = boxaGetBox(boxa, k, L_CLONE);
        boxGetGeometry(box, &x1, &y1, &bw, &bh);
        x2 = x1 + bw - 1;
        y2 = y1 + bh - 1;

            /* Remap gray pixels in the region */
        for (i = y1; i <= y2; i++) {
            if (i < 0 || i >= h)  /* clip */
                continue;
            line = data + i * wpl;
            for (j = x1; j <= x2; j++) {
                if (j < 0 || j >= w)  /* clip */
                    continue;
                val = GET_DATA_BYTE(line, j);
                if (val >= nc) continue;  /* from overlapping b.b. */
                nval = map[val];
                if (nval != 256)
                    SET_DATA_BYTE(line, j, nval);
            }
        }
        boxDestroy(&box);
    }

    FREE(map);
    return 0;
}
/*!
 *  pixColorGrayMaskedCmap()
 *
 *      Input:  pixs (8 bpp, with colormap)
 *              pixm (1 bpp mask, through which to apply color)
 *              type (L_PAINT_LIGHT, L_PAINT_DARK)
 *              rval, gval, bval (target color)
 *      Return: 0 if OK, 1 on error
 *
 *  Notes:
 *      (1) This is an in-place operation.
 *      (2) If type == L_PAINT_LIGHT, it colorizes non-black pixels,
 *          preserving antialiasing.
 *          If type == L_PAINT_DARK, it colorizes non-white pixels,
 *          preserving antialiasing.  See pixColorGrayCmap() for details.
 *      (3) This increases the colormap size by the number of
 *          different gray (non-black or non-white) colors in the
 *          input colormap.  If there is not enough room in the colormap
 *          for this expansion, it returns 1 (error).
 */
l_int32
pixColorGrayMaskedCmap(PIX     *pixs,
                       PIX     *pixm,
                       l_int32  type,
                       l_int32  rval,
                       l_int32  gval,
                       l_int32  bval)
{
l_int32    i, j, w, h, wm, hm, wmin, hmin, wpl, wplm;
l_int32    val, nval;
l_int32   *map;
l_uint32  *line, *data, *linem, *datam;
NUMA      *na;
PIXCMAP   *cmap;

    PROCNAME("pixColorGrayMaskedCmap");

    if (!pixs)
        return ERROR_INT("pixs not defined", procName, 1);
    if (!pixm || pixGetDepth(pixm) != 1)
        return ERROR_INT("pixm undefined or not 1 bpp", procName, 1);
    if ((cmap = pixGetColormap(pixs)) == NULL)
        return ERROR_INT("no colormap", procName, 1);
    if (pixGetDepth(pixs) != 8)
        return ERROR_INT("depth not 8 bpp", procName, 1);
    if (type != L_PAINT_DARK && type != L_PAINT_LIGHT)
        return ERROR_INT("invalid type", procName, 1);

    if (addColorizedGrayToCmap(cmap, type, rval, gval, bval, &na))
        return ERROR_INT("no room; cmap full", procName, 1);
    map = numaGetIArray(na);
    numaDestroy(&na);
    if (!map)
        return ERROR_INT("map not made", procName, 1);

    pixGetDimensions(pixs, &w, &h, NULL);
    pixGetDimensions(pixm, &wm, &hm, NULL);
    if (wm != w)
        L_WARNING("wm = %d differs from w = %d\n", procName, wm, w);
    if (hm != h)
        L_WARNING("hm = %d differs from h = %d\n", procName, hm, h);
    wmin = L_MIN(w, wm);
    hmin = L_MIN(h, hm);

    data = pixGetData(pixs);
    wpl = pixGetWpl(pixs);
    datam = pixGetData(pixm);
    wplm = pixGetWpl(pixm);

        /* Remap gray pixels in the region */
    for (i = 0; i < hmin; i++) {
        line = data + i * wpl;
        linem = datam + i * wplm;
        for (j = 0; j < wmin; j++) {
            if (GET_DATA_BIT(linem, j) == 0)
                continue;
            val = GET_DATA_BYTE(line, j);
            nval = map[val];
            if (nval != 256)
                SET_DATA_BYTE(line, j, nval);
        }
    }

    FREE(map);
    return 0;
}
Exemple #3
0
/*!
 *  pixColorGrayCmap()
 *
 *      Input:  pixs (2, 4 or 8 bpp, with colormap)
 *              box (<optional> region to set color; can be NULL)
 *              type (L_PAINT_LIGHT, L_PAINT_DARK)
 *              rval, gval, bval (target color)
 *      Return: 0 if OK, 1 on error
 *
 *  Notes:
 *      (1) This is an in-place operation.
 *      (2) If type == L_PAINT_LIGHT, it colorizes non-black pixels,
 *          preserving antialiasing.
 *          If type == L_PAINT_DARK, it colorizes non-white pixels,
 *          preserving antialiasing.
 *      (3) If box is NULL, applies function to the entire image; otherwise,
 *          clips the operation to the intersection of the box and pix.
 *      (4) This can also be called through pixColorGray().
 *      (5) This increases the colormap size by the number of
 *          different gray (non-black or non-white) colors in the
 *          input colormap.  If there is not enough room in the colormap
 *          for this expansion, it returns 1 (error), and the caller
 *          should check the return value.  If an error is returned
 *          and the cmap is only 2 or 4 bpp, the pix can be converted
 *          to 8 bpp and this function will succeed if run again on
 *          a larger colormap.
 *      (6) Using the darkness of each original pixel in the rect,
 *          it generates a new color (based on the input rgb values).
 *          If type == L_PAINT_LIGHT, the new color is a (generally)
 *          darken-to-black version of the  input rgb color, where the
 *          amount of darkening increases with the darkness of the
 *          original pixel color.
 *          If type == L_PAINT_DARK, the new color is a (generally)
 *          faded-to-white version of the  input rgb color, where the
 *          amount of fading increases with the brightness of the
 *          original pixel color.
 */
l_int32
pixColorGrayCmap(PIX     *pixs,
                 BOX     *box,
                 l_int32  type,
                 l_int32  rval,
                 l_int32  gval,
                 l_int32  bval)
{
l_int32    i, j, w, h, d, x1, y1, x2, y2, bw, bh, wpl;
l_int32    val, nval;
l_int32   *map;
l_uint32  *line, *data;
NUMA      *na;
PIX       *pixt;
PIXCMAP   *cmap, *cmapc;

    PROCNAME("pixColorGrayCmap");

    if (!pixs)
        return ERROR_INT("pixs not defined", procName, 1);
    if ((cmap = pixGetColormap(pixs)) == NULL)
        return ERROR_INT("no colormap", procName, 1);
    d = pixGetDepth(pixs);
    if (d != 2 && d != 4 && d != 8)
        return ERROR_INT("depth not in {2, 4, 8}", procName, 1);
    if (type != L_PAINT_DARK && type != L_PAINT_LIGHT)
        return ERROR_INT("invalid type", procName, 1);

        /* If 2 bpp or 4 bpp, see if the new colors will fit into
         * the existing colormap.  If not, convert in-place to 8 bpp. */
    if (d == 2 || d == 4) {
        cmapc = pixcmapCopy(cmap);  /* experiment with a copy */
        if (addColorizedGrayToCmap(cmapc, type, rval, gval, bval, NULL)) {
            pixt = pixConvertTo8(pixs, 1);
            pixTransferAllData(pixs, &pixt, 0, 0);
        }
        pixcmapDestroy(&cmapc);
    }

        /* Find gray colors, add the corresponding new colors,
         * and set up a mapping table from gray to new.
         * That table has the value 256 for all colors that are
         * not to be mapped. */
    cmap = pixGetColormap(pixs);
    if (addColorizedGrayToCmap(cmap, type, rval, gval, bval, &na)) {
        numaDestroy(&na);
        return ERROR_INT("no room; cmap full", procName, 1);
    }
    map = numaGetIArray(na);
    
        /* Determine the region of substitution */
    pixGetDimensions(pixs, &w, &h, &d);  /* d may be different */
    data = pixGetData(pixs);
    wpl = pixGetWpl(pixs);
    if (!box) {
        x1 = y1 = 0;
        x2 = w;
        y2 = h;
    }
    else {
        boxGetGeometry(box, &x1, &y1, &bw, &bh);
        x2 = x1 + bw - 1;
        y2 = y1 + bh - 1;
    }

        /* Remap gray pixels in the region */
    for (i = y1; i <= y2; i++) {
        if (i < 0 || i >= h)  /* clip */
            continue;
        line = data + i * wpl;
        for (j = x1; j <= x2; j++) {
            if (j < 0 || j >= w)  /* clip */
                continue;
            switch (d)
            {
            case 2:
                val = GET_DATA_DIBIT(line, j);
                nval = map[val];
                if (nval != 256)
                    SET_DATA_DIBIT(line, j, nval);
                break;
            case 4:
                val = GET_DATA_QBIT(line, j);
                nval = map[val];
                if (nval != 256)
                    SET_DATA_QBIT(line, j, nval);
                break;
            case 8:
                val = GET_DATA_BYTE(line, j);
                nval = map[val];
                if (nval != 256)
                    SET_DATA_BYTE(line, j, nval);
                break;
            }
        }
    }

    FREE(map);
    numaDestroy(&na);
    return 0;
}