/*! * pixcmapAddBlackOrWhite() * * Input: cmap * color (0 for black, 1 for white) * &index (<optional return> index of color; can be null) * Return: 0 if OK, 1 on error * * Notes: * (1) This only adds color if not already there. * (2) This sets index to the requested color. * (3) If there is no room in the colormap, returns the index * of the closest color. */ l_int32 pixcmapAddBlackOrWhite(PIXCMAP *cmap, l_int32 color, l_int32 *pindex) { l_int32 index; PROCNAME("pixcmapAddBlackOrWhite"); if (pindex) *pindex = 0; if (!cmap) return ERROR_INT("cmap not defined", procName, 1); if (color == 0) { /* black */ if (pixcmapGetFreeCount(cmap) > 0) pixcmapAddNewColor(cmap, 0, 0, 0, &index); else pixcmapGetRankIntensity(cmap, 0.0, &index); } else { /* white */ if (pixcmapGetFreeCount(cmap) > 0) pixcmapAddNewColor(cmap, 255, 255, 255, &index); else pixcmapGetRankIntensity(cmap, 1.0, &index); } if (pindex) *pindex = index; return 0; }
/*! * addColorizedGrayToCmap() * * Input: cmap (from 2 or 4 bpp pix) * type (L_PAINT_LIGHT, L_PAINT_DARK) * rval, gval, bval (target color) * &na (<optional return> table for mapping new cmap entries) * Return: 0 if OK; 1 on error; 2 if new colors will not fit in cmap. * * Notes: * (1) If type == L_PAINT_LIGHT, it colorizes non-black pixels, * preserving antialiasing. * If type == L_PAINT_DARK, it colorizes non-white pixels, * preserving antialiasing. * (2) 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 (treated as a warning); * the caller should check the return value. * (3) This can be used to determine if the new colors will fit in * the cmap, using null for &na. Returns 0 if they fit; 2 if * they don't fit. * (4) The mapping table contains, for each gray color found, the * index of the corresponding colorized pixel. Non-gray * pixels are assigned the invalid index 256. * (5) See pixColorGrayCmap() for usage. */ l_int32 addColorizedGrayToCmap(PIXCMAP *cmap, l_int32 type, l_int32 rval, l_int32 gval, l_int32 bval, NUMA **pna) { l_int32 i, n, erval, egval, ebval, nrval, ngval, nbval, newindex; NUMA *na; PROCNAME("addColorizedGrayToCmap"); if (pna) *pna = NULL; if (!cmap) return ERROR_INT("cmap not defined", procName, 1); if (type != L_PAINT_DARK && type != L_PAINT_LIGHT) return ERROR_INT("invalid type", procName, 1); n = pixcmapGetCount(cmap); na = numaCreate(n); for (i = 0; i < n; i++) { pixcmapGetColor(cmap, i, &erval, &egval, &ebval); if (type == L_PAINT_LIGHT) { if (erval == egval && erval == ebval && erval != 0) { nrval = (l_int32)(rval * (l_float32)erval / 255.); ngval = (l_int32)(gval * (l_float32)egval / 255.); nbval = (l_int32)(bval * (l_float32)ebval / 255.); if (pixcmapAddNewColor(cmap, nrval, ngval, nbval, &newindex)) { numaDestroy(&na); L_WARNING("no room; colormap full\n", procName); return 2; } numaAddNumber(na, newindex); } else { numaAddNumber(na, 256); /* invalid number; not gray */ } } else { /* L_PAINT_DARK */ if (erval == egval && erval == ebval && erval != 255) { nrval = rval + (l_int32)((255. - rval) * (l_float32)erval / 255.); ngval = gval + (l_int32)((255. - gval) * (l_float32)egval / 255.); nbval = bval + (l_int32)((255. - bval) * (l_float32)ebval / 255.); if (pixcmapAddNewColor(cmap, nrval, ngval, nbval, &newindex)) { numaDestroy(&na); L_WARNING("no room; colormap full\n", procName); return 2; } numaAddNumber(na, newindex); } else { numaAddNumber(na, 256); /* invalid number; not gray */ } } } if (pna) *pna = na; else numaDestroy(&na); 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; }