/*!
 *  pixCopyColormap()
 *
 *      Input:  src and dest Pix
 *      Return: 0 if OK, 1 on error
 *
 *  Notes:
 *      (1) This always destroys any colormap in pixd (except if
 *          the operation is a no-op.
 */
l_int32
pixCopyColormap(PIX  *pixd,
                PIX  *pixs)
{
PIXCMAP  *cmaps, *cmapd;

    PROCNAME("pixCopyColormap");

    if (!pixs)
        return ERROR_INT("pixs not defined", procName, 1);
    if (!pixd)
        return ERROR_INT("pixd not defined", procName, 1);
    if (pixs == pixd)
        return 0;   /* no-op */

    pixDestroyColormap(pixd);
    if ((cmaps = pixGetColormap(pixs)) == NULL)  /* not an error */
        return 0;

    if ((cmapd = pixcmapCopy(cmaps)) == NULL)
        return ERROR_INT("cmapd not made", procName, 1);
    pixSetColormap(pixd, cmapd);

    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;
}
示例#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;
}